package com.mlethe.library.widget.banner;

import androidx.annotation.IntRange;
import androidx.annotation.NonNull;

import java.util.Collections;
import java.util.List;

/**
 * Created by Mlethe on 2018/5/29.
 */
public abstract class BannerAdapter<T> {

    private BannerView.AdapterDataObservable mObservable = new BannerView.AdapterDataObservable();

    private List<T> mData;

    public BannerAdapter(List<T> data) {
        this.mData = data;
    }

    /**
     * 获取数据
     *
     * @return
     */
    public final List<T> getData() {
        return mData;
    }

    /**
     * 获取轮播的数量
     *
     * @return
     */
    public final int getCount() {
        if (mData == null) {
            return 0;
        }
        return mData.size();
    }

    /**
     * 销毁数据
     */
    public void onDestroy() {
    }

    /**
     * 获取单条数据
     *
     * @param position
     * @return
     */
    public T getItem(@IntRange(from = 0) int position) {
        if (mData != null && position < mData.size()) {
            return mData.get(position);
        }
        return null;
    }

    /**
     * 添加数据
     *
     * @param element
     */
    public boolean addItem(T element) {
        if (mData != null && element != null) {
            return mData.add(element);
        }
        return false;
    }

    /**
     * 添加数据
     *
     * @param position
     * @param element
     */
    public void addItem(@IntRange(from = 0) int position, T element) {
        if (mData != null && element != null) {
            mData.add(position, element);
        }
    }

    /**
     * 添加列表数据
     *
     * @param list
     */
    public boolean addAllItem(List<T> list) {
        if (mData != null && list != null && list.size() > 0) {
            // 去除null元素
            list.removeAll(Collections.singleton(null));
            return mData.addAll(list);
        }
        return false;
    }

    /**
     * 添加列表数据
     *
     * @param list
     */
    public boolean addAllItem(@IntRange(from = 0) int position, List<T> list) {
        if (mData != null && list != null && list.size() > 0) {
            // 去除null元素
            list.removeAll(Collections.singleton(null));
            return mData.addAll(position, list);
        }
        return false;
    }

    /**
     * 修改数据
     *
     * @param position
     * @param element
     */
    public T setItem(@IntRange(from = 0) int position, T element) {
        if (mData != null && element != null) {
            return mData.set(position, element);
        }
        return null;
    }

    /**
     * 删除数据
     *
     * @param position
     */
    public T removeItem(@IntRange(from = 0) int position) {
        if (mData != null) {
            return mData.remove(position);
        }
        return null;
    }

    /**
     * 删除数据
     *
     * @param element
     */
    public T removeItem(T element) {
        if (mData != null && element != null) {
            int index = mData.indexOf(element);
            if (index != -1) {
                return mData.remove(index);
            }
        }
        return null;
    }

    /**
     * 移动数据
     *
     * @param fromPosition
     * @param toPosition
     */
    public void moveItem(@IntRange(from = 0) int fromPosition, @IntRange(from = 0) int toPosition) {
        if (mData != null) {
            mData.add(toPosition, mData.remove(fromPosition));
        }
    }

    /**
     * 清除数据
     */
    public void clearItems() {
        if (mData != null) {
            mData.clear();
        }
    }

    /**
     * 获取根据位置获取ViewPager里面的子布局
     *
     * @param position
     */
    protected abstract int getLayoutId(T item, int position);

    /**
     * 绑定数据
     *
     * @param position
     * @return
     */
    protected abstract void convert(BannerView.ViewHolder holder, T item, int position);

    /**
     * 当前展示数据
     *
     * @param item
     * @param position
     */
    protected void onCurrentItem(T item, int position) {
    }

    /**
     * 获取播放时间
     *
     * @param position
     * @return
     */
    protected long getRollTime(T item, int position) {
        return 0;
    }

    /**
     * Register a new observer to listen for data changes.
     *
     * <p>The adapter may publish a variety of events describing specific changes.
     * Not all adapters may support all change types and some may fall back to a generic
     * {@link BannerView.AdapterDataObserver#onChanged()
     * "something changed"} event if more specific data is not available.</p>
     *
     * <p>Components registering observers with an adapter are responsible for
     * {@link #unregisterAdapterDataObserver(BannerView.AdapterDataObserver)
     * unregistering} those observers when finished.</p>
     *
     * @param observer Observer to register
     * @see #unregisterAdapterDataObserver(BannerView.AdapterDataObserver)
     */
    public void registerAdapterDataObserver(@NonNull BannerView.AdapterDataObserver observer) {
        mObservable.registerObserver(observer);
    }

    /**
     * Unregister an observer currently listening for data changes.
     *
     * <p>The unregistered observer will no longer receive events about changes
     * to the adapter.</p>
     *
     * @param observer Observer to unregister
     * @see #registerAdapterDataObserver(BannerView.AdapterDataObserver)
     */
    public void unregisterAdapterDataObserver(@NonNull BannerView.AdapterDataObserver observer) {
        mObservable.unregisterObserver(observer);
    }

    /**
     * Called by RecyclerView when it starts observing this Adapter.
     * <p>
     * Keep in mind that same adapter may be observed by multiple RecyclerViews.
     *
     * @param bannerView The RecyclerView instance which started observing this adapter.
     * @see #onDetachedFromBannerView(BannerView)
     */
    public void onAttachedToBannerView(@NonNull BannerView bannerView) {
    }

    /**
     * Called by RecyclerView when it stops observing this Adapter.
     *
     * @param bannerView The RecyclerView instance which stopped observing this adapter.
     * @see #onAttachedToBannerView(BannerView)
     */
    public final void onDetachedFromBannerView(@NonNull BannerView bannerView) {
        if (mData != null) {
            mData.clear();
            mData = null;
        }
        onDestroy();
    }

    /**
     * Notify any registered observers that the data set has changed.
     *
     * <p>There are two different classes of data change events, item changes and structural
     * changes. Item changes are when a single item has its data updated but no positional
     * changes have occurred. Structural changes are when items are inserted, removed or moved
     * within the data set.</p>
     *
     * <p>This event does not specify what about the data set has changed, forcing
     * any observers to assume that all existing items and structure may no longer be valid.
     * LayoutManagers will be forced to fully rebind and relayout all visible views.</p>
     *
     * <p><code>RecyclerView</code> will attempt to synthesize visible structural change events
     * for adapters that report that they have {@link #() stable IDs} when
     * this method is used. This can help for the purposes of animation and visual
     * object persistence but individual item views will still need to be rebound
     * and relaid out.</p>
     *
     * <p>If you are writing an adapter it will always be more efficient to use the more
     * specific change events if you can. Rely on <code>notifyDataSetChanged()</code>
     * as a last resort.</p>
     */
    public final void notifyDataSetChanged() {
        mObservable.notifyChanged();
    }
}
